home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / strategy / xpuzzles.3 / xpuzzles / xpuzzles-5.3.1 / xdino / Dino.c < prev    next >
C/C++ Source or Header  |  1996-04-02  |  32KB  |  1,156 lines

  1. /*
  2. # X-BASED DINOSAUR CUBE
  3. #
  4. #  Dino.c
  5. #
  6. ###
  7. #
  8. #  Copyright (c) 1995 - 96    David Albert Bagley, bagleyd@hertz.njit.edu
  9. #
  10. #                   All Rights Reserved
  11. #
  12. #  Permission to use, copy, modify, and distribute this software and
  13. #  its documentation for any purpose and without fee is hereby granted,
  14. #  provided that the above copyright notice appear in all copies and
  15. #  that both that copyright notice and this permission notice appear in
  16. #  supporting documentation, and that the name of the author not be
  17. #  used in advertising or publicity pertaining to distribution of the
  18. #  software without specific, written prior permission.
  19. #
  20. #  This program is distributed in the hope that it will be "playable",
  21. #  but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  23. #
  24. */
  25.  
  26. /* Methods file for Dino */
  27.  
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #ifdef VMS
  31. #include <unixlib.h>
  32. #else
  33. #ifndef apollo
  34. #include <unistd.h>
  35. #endif
  36. #endif
  37. #include <X11/IntrinsicP.h>
  38. #include <X11/Intrinsic.h>
  39. #include <X11/StringDefs.h>
  40. #include <X11/CoreP.h>
  41. #include "DinoP.h"
  42. #include "Dino2dP.h"
  43. #include "Dino3dP.h"
  44.  
  45. #ifndef DATAFILE
  46. #define DATAFILE "/usr/games/lib/dino.data"
  47. #endif
  48.  
  49. static void InitializeDino();
  50. static void DestroyDino();
  51. static Boolean SetValuesDino();
  52. static void GetColor();
  53. static void MoveControlCb();
  54. static void CheckPolyhedrons();
  55. static void ResetPolyhedrons();
  56. static int SelectPolyhedrons();
  57. static int NarrowSelection();
  58. static int PositionPolyhedrons();
  59. static int GetStyle();
  60. static void MoveNoPolyhedrons();
  61. static void PracticePolyhedrons();
  62. static void RandomizePolyhedrons();
  63. static void MovePolyhedrons();
  64. static void MoveInsideCorners();
  65. static void MoveOutsideCorners();
  66. static void MoveEdges();
  67. static void MoveFaces();
  68. static void ReadDiagonal();
  69. static void WriteDiagonal();
  70. static void ReadFace();
  71. static void WriteFace();
  72. static void RotateFace();
  73. static void DrawTriangle();
  74. static int CheckMoveDir();
  75.  
  76. DinoClassRec dinoClassRec =
  77. {
  78.   {
  79.     (WidgetClass) &widgetClassRec,    /* superclass */
  80.     "Dino",                /* class name */
  81.     sizeof(DinoRec),            /* widget size */
  82.     NULL,                /* class initialize */
  83.     NULL,                /* class part initialize */
  84.     FALSE,                /* class inited */
  85.     InitializeDino,            /* initialize */
  86.     NULL,                /* initialize hook */
  87.     XtInheritRealize,            /* realize */
  88.     NULL,                /* actions */
  89.     0,                    /* num actions */
  90.     NULL,                /* resources */
  91.     0,                    /* num resources */
  92.     NULLQUARK,                /* xrm class */
  93.     TRUE,                /* compress motion */
  94.     TRUE,                /* compress exposure */
  95.     TRUE,                /* compress enterleave */
  96.     TRUE,                /* visible interest */
  97.     DestroyDino,            /* destroy */
  98.     NULL,                /* resize */
  99.     NULL,                /* expose */
  100.     SetValuesDino,            /* set values */
  101.     NULL,                /* set values hook */
  102.     XtInheritSetValuesAlmost,        /* set values almost */
  103.     NULL,                /* get values hook */
  104.     NULL,                /* accept focus */
  105.     XtVersion,                /* version */
  106.     NULL,                /* callback private */
  107.     NULL,                /* tm table */
  108.     NULL,                /* query geometry */
  109.     NULL,                /* display accelerator */
  110.     NULL                /* extension */
  111.   },
  112.   {
  113.     0                    /* ignore */
  114.   }
  115. };
  116.  
  117. WidgetClass dinoWidgetClass = (WidgetClass) &dinoClassRec;
  118.  
  119. static DinoLoc slideCorner[MAXFACES][MAXORIENT][MAXORIENT/2] =
  120. {
  121.   {
  122.     {{3, TR, 0}, {5, BR, 0}},
  123.     {{3, TL, 1}, {2, TR, 0}},
  124.     {{2, TL, 1}, {1, TR, 0}},
  125.     {{5, BL, 1}, {1, TL, 1}}
  126.   },
  127.   {
  128.     {{2, TL, 0}, {0, BL, 0}},
  129.     {{2, BL, 0}, {4, TL, 0}},
  130.     {{4, BL, 0}, {5, TL, 0}},
  131.     {{0, TL, 0}, {5, BL, 0}}
  132.   },
  133.   {
  134.     {{3, TL, 0}, {0, BR, 0}},
  135.     {{3, BL, 0}, {4, TR, 0}},
  136.     {{4, TL, 1}, {1, BR, 1}},
  137.     {{0, BL, 1}, {1, TR, 1}}
  138.   },
  139.   {
  140.     {{5, BR, 1}, {0, TR, 1}},
  141.     {{5, TR, 1}, {4, BR, 1}},
  142.     {{4, TR, 1}, {2, BR, 1}},
  143.     {{0, BR, 1}, {2, TR, 1}}
  144.   },
  145.   {
  146.     {{3, BL, 1}, {2, BR, 0}},
  147.     {{3, BR, 0}, {5, TR, 0}},
  148.     {{5, TL, 1}, {1, BL, 1}},
  149.     {{2, BL, 1}, {1, BR, 0}}
  150.   },
  151.   {
  152.     {{3, BR, 1}, {4, BR, 0}},
  153.     {{3, TR, 1}, {0, TR, 0}},
  154.     {{0, TL, 1}, {1, TL, 0}},
  155.     {{4, BL, 1}, {1, BL, 0}}
  156.   }
  157. };
  158.  
  159. static int oppFace[MAXFACES] = {4, 3, 5, 1, 0, 2};
  160.  
  161. static DinoCornerLoc oppCorner[MAXFACES][MAXORIENT] =
  162. {
  163.   {{4, 3}, {4, 2}, {4, 1}, {4, 0}},
  164.   {{3, 1}, {3, 0}, {3, 3}, {3, 2}},
  165.   {{5, 3}, {5, 2}, {5, 1}, {5, 0}},
  166.   {{1, 1}, {1, 0}, {1, 3}, {1, 2}},
  167.   {{0, 3}, {0, 2}, {0, 1}, {0, 0}},
  168.   {{2, 3}, {2, 2}, {2, 1}, {2, 0}}
  169. };
  170.  
  171. /*static int slideNextFace2[MAXFACES] = {4, 3, 5, 1, 0, 2};*/
  172.  
  173. static DinoCornerLoc slideNextFace[MAXFACES][MAXORIENT] =
  174. {
  175.   {{5, STRT}, {3,   CW}, {2, STRT}, {1,  CCW}},
  176.   {{0,   CW}, {2, STRT}, {4,  CCW}, {5, HALF}},
  177.   {{0, STRT}, {3, STRT}, {4, STRT}, {1, STRT}},
  178.   {{0,  CCW}, {5, HALF}, {4,   CW}, {2, STRT}},
  179.   {{2, STRT}, {3,  CCW}, {5, STRT}, {1,   CW}},
  180.   {{4, STRT}, {3, HALF}, {0, STRT}, {1, HALF}}
  181. };
  182.  
  183. static int faceToRotate2[MAXFACES][MAXORIENT][2] =
  184. {
  185.   {{3, 5}, {2, 3}, {1, 2}, {1, 5}},
  186.   {{0, 2}, {2, 4}, {4, 5}, {0, 5}},
  187.   {{3, 0}, {4, 3}, {1, 4}, {0, 1}},
  188.   {{0, 5}, {4, 5}, {2, 4}, {0, 2}},
  189.   {{2, 3}, {3, 5}, {1, 5}, {1, 2}},
  190.   {{4, 3}, {3, 0}, {0, 1}, {1, 4}}
  191. };
  192.  
  193. static int faceToRotate[MAXFACES][MAXORIENT] =
  194. {
  195.   {3, 2, 1, 5},
  196.   {2, 4, 5, 0},
  197.   {3, 4, 1, 0},
  198.   {5, 4, 2, 0},
  199.   {3, 5, 1, 2},
  200.   {3, 0, 1, 4}
  201. };
  202.  
  203. static void InitializeDino(request, new)
  204.   Widget request, new;
  205. {
  206.   DinoWidget w = (DinoWidget) new;
  207.   XGCValues values;
  208.   XtGCMask valueMask;
  209.   int face;
  210.  
  211.   CheckPolyhedrons(w);
  212.   InitMoves();
  213.   ResetPolyhedrons(w);
  214.   (void) SRAND(getpid());
  215.   valueMask = GCForeground | GCBackground;
  216.   values.background = w->core.background_pixel;
  217.   values.foreground = w->dino.foreground;
  218.   w->dino.puzzleGC = XtGetGC(new, valueMask, &values);
  219.   values.foreground = w->dino.borderColor;
  220.   w->dino.borderGC = XtGetGC(new, valueMask, &values);
  221.   w->dino.depth = DefaultDepthOfScreen(XtScreen(w));
  222.   valueMask = GCForeground | GCBackground;
  223.   values.foreground = w->core.background_pixel;
  224.   values.background = w->dino.foreground;
  225.   w->dino.inverseGC = XtGetGC(new, valueMask, &values);
  226.   for (face = 0; face < MAXFACES; face++)
  227.     GetColor(w, face, TRUE);
  228. }
  229.  
  230. static void DestroyDino(old)
  231.   Widget old;
  232. {
  233.   DinoWidget w = (DinoWidget) old;
  234.   int face;
  235.  
  236.   for (face = 0; face < MAXFACES; face++)
  237.     XtReleaseGC(old, w->dino.faceGC[face]);
  238.   XtReleaseGC(old, w->dino.borderGC);
  239.   XtReleaseGC(old, w->dino.puzzleGC);
  240.   XtReleaseGC(old, w->dino.inverseGC);
  241.   XtRemoveCallbacks(old, XtNselectCallback, w->dino.select);
  242. }
  243.  
  244. static Boolean SetValuesDino(current, request, new)
  245.   Widget current, request, new;
  246. {
  247.   DinoWidget c = (DinoWidget) current, w = (DinoWidget) new;
  248.   XGCValues values;
  249.   XtGCMask valueMask;
  250.   Boolean redraw = FALSE;
  251.   int face;
  252.  
  253.   if (w->dino.foreground != c->dino.foreground) {
  254.     valueMask = GCForeground | GCBackground;
  255.     values.foreground = w->dino.foreground;
  256.     values.background = w->core.background_pixel;
  257.     XtReleaseGC(new, w->dino.puzzleGC);
  258.     w->dino.puzzleGC = XtGetGC(new, valueMask, &values);
  259.     redraw = TRUE;
  260.   }
  261.   if (w->core.background_pixel != c->core.background_pixel) {
  262.     valueMask = GCForeground | GCBackground;
  263.     values.foreground = w->core.background_pixel;
  264.     values.background = w->dino.foreground;
  265.     XtReleaseGC(new, w->dino.inverseGC);
  266.     w->dino.inverseGC = XtGetGC(new, valueMask, &values);
  267.     redraw = TRUE;
  268.   }
  269.   if (w->dino.borderColor != c->dino.borderColor) {
  270.     valueMask = GCForeground | GCBackground;
  271.     values.foreground = w->dino.borderColor;
  272.     values.background = w->core.background_pixel;
  273.     XtReleaseGC(new, w->dino.borderGC);
  274.     w->dino.borderGC = XtGetGC(new, valueMask, &values);
  275.     redraw = TRUE;
  276.   }
  277.   if (w->dino.mono || w->dino.depth == 1) {
  278.     valueMask = GCForeground | GCBackground;
  279.     values.background = w->core.background_pixel;
  280.     values.foreground = w->dino.foreground;
  281.     for (face = 0; face < MAXFACES; face++) {
  282.       XtReleaseGC(new, w->dino.faceGC[face]);
  283.       w->dino.faceGC[face] = XtGetGC(new, valueMask, &values);
  284.     }
  285.     redraw = TRUE;
  286.   }
  287.   for (face = 0; face < MAXFACES; face++) {
  288.     if (strcmp(w->dino.faceName[face], c->dino.faceName[face]))
  289.       GetColor(w, face, FALSE);
  290.   }
  291.   if (w->dino.orient != c->dino.orient) {
  292.     ResetPolyhedrons(w);
  293.     redraw = TRUE;
  294.   } else if (w->dino.practice != c->dino.practice) {
  295.     ResetPolyhedrons(w);
  296.     redraw = TRUE;
  297.   }
  298.   if (w->dino.mode != c->dino.mode) {
  299.     ResetPolyhedrons(w);
  300.     redraw = TRUE;
  301.   }
  302.   if (w->dino.currentDirection == DINO_RESTORE) {
  303.     SetStartPosition(w);
  304.     w->dino.currentDirection = DINO_IGNORE;
  305.   } else if (w->dino.currentDirection != DINO_IGNORE) {
  306.     MovePolyhedrons(w, w->dino.currentFace, w->dino.currentPosition,
  307.       w->dino.currentDirection, w->dino.style);
  308.     w->dino.currentDirection = DINO_IGNORE;
  309.   }
  310.   return redraw;
  311. }
  312.  
  313. void QuitDino(w, event, args, nArgs)
  314.   DinoWidget w;
  315.   XEvent *event;
  316.   char *args[];
  317.   int nArgs;
  318. {
  319.   XtCloseDisplay(XtDisplay(w));
  320.   exit(0);
  321. }
  322.  
  323. void SelectDino(w, event, args, nArgs)
  324.   DinoWidget w;
  325.   XEvent *event;
  326.   char *args[];
  327.   int nArgs;
  328. {
  329.   int control;
  330.  
  331.   if (SelectPolyhedrons(w, event->xbutton.x, event->xbutton.y,
  332.              &(w->dino.currentFace), &(w->dino.currentPosition))) {
  333.     control = (int) (event->xkey.state & ControlMask);
  334.     if (control || w->dino.practice || !CheckSolved(w))
  335.       DrawTriangle(w, w->dino.currentFace, w->dino.currentPosition,
  336.         TRUE);
  337.   } else {
  338.     w->dino.currentFace = DINO_IGNORE;
  339.     w->dino.currentDirection = DINO_IGNORE;
  340.   }
  341. }
  342.  
  343. void ReleaseDino(w, event, args, nArgs)
  344.   DinoWidget w;
  345.   XEvent *event;
  346.   char *args[];
  347.   int nArgs;
  348. {
  349.   int shift, control, alt, style, face, position, count = -1, direction = 0;
  350.   dinoCallbackStruct cb;
  351.  
  352.   if (w->dino.currentFace == DINO_IGNORE)
  353.     return;
  354.   DrawTriangle(w, w->dino.currentFace, w->dino.currentPosition, FALSE);
  355.   shift = (int) (event->xbutton.state & (ShiftMask | LockMask));
  356.   control = (int) (event->xkey.state & ControlMask);
  357.   alt = (int) (event->xkey.state &
  358.       (Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask));
  359.   style = GetStyle(w, shift, control, alt);
  360.   if (!control && !w->dino.practice && CheckSolved(w))
  361.     MoveNoPolyhedrons(w);
  362.   else if (SelectPolyhedrons(w, event->xbutton.x, event->xbutton.y,
  363.              &face, &position) && position != w->dino.currentPosition) {
  364.     control = (control) ? 1 : 0;
  365.     if (face == w->dino.currentFace)
  366.       count = CheckMoveDir(w->dino.currentPosition, position, &direction);
  367.     if (count == 1) {
  368.       MoveDino(w, face, w->dino.currentPosition, direction, style, control);
  369.       if (!control && CheckSolved(w)) {
  370.         cb.reason = DINO_SOLVED;
  371.         XtCallCallbacks((Widget) w, XtNselectCallback, &cb);
  372.       }
  373.     } else if (count == 0)
  374.       MoveNoPolyhedrons(w);
  375.   }
  376.   w->dino.currentFace = DINO_IGNORE;
  377.   w->dino.currentDirection = DINO_IGNORE;
  378. }
  379.  
  380. void PracticeDino(w, event, args, nArgs)
  381.   DinoWidget w;
  382.   XEvent *event;
  383.   char *args[];
  384.   int nArgs;
  385. {
  386.   PracticePolyhedrons(w);
  387. }
  388.  
  389. void PracticeDinoMaybe(w, event, args, nArgs)
  390.   DinoWidget w;
  391.   XEvent *event;
  392.   char *args[];
  393.   int nArgs;
  394. {
  395.   if (!w->dino.started)
  396.     PracticePolyhedrons(w);
  397. }
  398.  
  399. void RandomizeDino(w, event, args, nArgs)
  400.   DinoWidget w;
  401.   XEvent *event;
  402.   char *args[];
  403.   int nArgs;
  404. {
  405.   RandomizePolyhedrons(w);
  406. }
  407.  
  408. void RandomizeDinoMaybe(w, event, args, nArgs)
  409.   DinoWidget w;
  410.   XEvent *event;
  411.   char *args[];
  412.   int nArgs;
  413. {
  414.   if (!w->dino.started)
  415.     RandomizePolyhedrons(w);
  416. }
  417.  
  418. void GetDino(w, event, args, nArgs)
  419.   DinoWidget w;
  420.   XEvent *event;
  421.   char *args[];
  422.   int nArgs;
  423. {
  424.   FILE *fp;
  425.   char c;
  426.   int mode, orient, practice, moves;
  427.   dinoCallbackStruct cb;
  428.  
  429.   if ((fp = fopen(DATAFILE, "r")) == NULL)
  430.     (void) printf("Can not read %s for get.\n", DATAFILE);
  431.   else {
  432.     FlushMoves(w);
  433.     while ((c = getc(fp)) != EOF && c != SYMBOL);
  434.     (void) fscanf(fp, "%d", &mode);
  435.     if (mode >= PERIOD2 && mode <= BOTH)
  436.       switch (mode) {
  437.         case PERIOD2:
  438.           cb.reason = DINO_PERIOD2;
  439.           XtCallCallbacks((Widget) w, XtNselectCallback, &cb);
  440.           break;
  441.         case PERIOD3:
  442.           cb.reason = DINO_PERIOD3;
  443.           XtCallCallbacks((Widget) w, XtNselectCallback, &cb);
  444.           break;
  445.         case BOTH:
  446.           cb.reason = DINO_BOTH;
  447.           XtCallCallbacks((Widget) w, XtNselectCallback, &cb);
  448.       }
  449.     else
  450.       (void) printf("%s corrupted: mode %d should be between %d and %d\n",
  451.          DATAFILE, mode, PERIOD2, BOTH);
  452.     while ((c = getc(fp)) != EOF && c != SYMBOL);
  453.     (void) fscanf(fp, "%d", &orient);
  454.     if (w->dino.orient != (Boolean) orient) {
  455.       cb.reason = DINO_ORIENT;
  456.       XtCallCallbacks((Widget) w, XtNselectCallback, &cb);
  457.     }
  458.     while ((c = getc(fp)) != EOF && c != SYMBOL);
  459.     (void) fscanf(fp, "%d", &practice);
  460.     if (w->dino.practice != (Boolean) practice) {
  461.       cb.reason = DINO_PRACTICE;
  462.       XtCallCallbacks((Widget) w, XtNselectCallback, &cb);
  463.     }
  464.     while ((c = getc(fp)) != EOF && c != SYMBOL);
  465.     (void) fscanf(fp, "%d", &moves);
  466.     ScanStartPosition(fp, w);
  467.     cb.reason = DINO_RESTORE;
  468.     XtCallCallbacks((Widget) w, XtNselectCallback, &cb);
  469.     ScanMoves(fp, w, moves);
  470.     (void) fclose(fp);
  471.     (void) printf("%s: mode %d, orient %d, practice %d, moves %d.\n",
  472.       DATAFILE, mode, orient, practice, moves);
  473.   }
  474. }
  475.  
  476. void WriteDino(w, event, args, nArgs)
  477.   DinoWidget w;
  478.   XEvent *event;
  479.   char *args[];
  480.   int nArgs;
  481. {
  482.   FILE *fp;
  483.  
  484.   if ((fp = fopen(DATAFILE, "w")) == NULL)
  485.     (void) printf("Can not write to %s.\n", DATAFILE);
  486.   else {
  487.     (void) fprintf(fp, "dino%c %d\n", SYMBOL, w->dino.mode);
  488.     (void) fprintf(fp, "orient%c %d\n", SYMBOL, (w->dino.orient) ? 1 : 0);
  489.     (void) fprintf(fp, "practice%c %d\n", SYMBOL, (w->dino.practice) ? 1 : 0);
  490.     (void) fprintf(fp, "moves%c %d\n", SYMBOL, NumMoves());
  491.     PrintStartPosition(fp, w);
  492.     PrintMoves(fp);
  493.     (void) fclose(fp);
  494.     (void) printf("Saved to %s.\n", DATAFILE);
  495.   }
  496. }
  497.  
  498. void UndoDino(w, event, args, nArgs)
  499.   DinoWidget w;
  500.   XEvent *event;
  501.   char *args[];
  502.   int nArgs;
  503. {
  504.   if (MadeMoves()) {
  505.     int face, position, direction, style, control;
  506.  
  507.     GetMove(&face, &position, &direction, &style, &control);
  508.     direction = (direction < MAXORIENT) ? (direction + MAXORIENT / 2) %
  509.       MAXORIENT : 5 * MAXORIENT - direction;
  510.     if (control)
  511.       MoveControlCb(w, face, position, direction, style);
  512.     else {
  513.       dinoCallbackStruct cb;
  514.  
  515.       MovePolyhedrons(w, face, position, direction, style);
  516.       cb.reason = DINO_UNDO;
  517.       cb.face = face;
  518.       cb.position = position;
  519.       cb.direction = direction;
  520.       cb.style = style;
  521.       XtCallCallbacks((Widget) w, XtNselectCallback, &cb);
  522.     }
  523.   }
  524. }
  525.  
  526. void SolveDino(w, event, args, nArgs)
  527.   DinoWidget w;
  528.   XEvent *event;
  529.   char *args[];
  530.   int nArgs;
  531. {
  532.   /* SolvePolyhedrons(w); */ /* Sorry, unimplemented */
  533. }
  534.  
  535. void OrientizeDino(w, event, args, nArgs)
  536.   DinoWidget w;
  537.   XEvent *event;
  538.   char *args[];
  539.   int nArgs;
  540. {
  541.   dinoCallbackStruct cb;
  542.  
  543.   cb.reason = DINO_ORIENT;
  544.   XtCallCallbacks((Widget) w, XtNselectCallback, &cb);
  545. }
  546.  
  547. void Period2ModeDino(w, event, args, nArgs)
  548.   DinoWidget w;
  549.   XEvent *event;
  550.   char *args[];
  551.   int nArgs;
  552. {
  553.   dinoCallbackStruct cb;
  554.  
  555.   cb.reason = DINO_PERIOD2;
  556.   XtCallCallbacks((Widget) w, XtNselectCallback, &cb);
  557. }
  558.  
  559. void Period3ModeDino(w, event, args, nArgs)
  560.   DinoWidget w;
  561.   XEvent *event;
  562.   char *args[];
  563.   int nArgs;
  564. {
  565.   dinoCallbackStruct cb;
  566.  
  567.   cb.reason = DINO_PERIOD3;
  568.   XtCallCallbacks((Widget) w, XtNselectCallback, &cb);
  569. }
  570.  
  571. void BothModeDino(w, event, args, nArgs)
  572.   DinoWidget w;
  573.   XEvent *event;
  574.   char *args[];
  575.   int nArgs;
  576. {
  577.   dinoCallbackStruct cb;
  578.  
  579.   cb.reason = DINO_BOTH;
  580.   XtCallCallbacks((Widget) w, XtNselectCallback, &cb);
  581. }
  582.  
  583. void MoveDinoInput(w, x, y, direction, shift, control, alt)
  584.   DinoWidget w;
  585.   int x, y, direction, shift, control, alt;
  586. {
  587.   int face, position, style;
  588.  
  589.   if (!w->dino.practice && !control && CheckSolved(w)) {
  590.     MoveNoPolyhedrons(w);
  591.     return;
  592.   }
  593.   if (!PositionPolyhedrons(w, x, y, &face, &position, &direction))
  594.     return;
  595.   if (direction >= 2 * MAXORIENT) {
  596.     if (control)
  597.       style = FACE;
  598.     else
  599.        return;
  600.   } else
  601.     style = GetStyle(w, shift, control, alt);
  602.   control = (control) ? 1 : 0;
  603.   MoveDino(w, face, position, direction, style, control);
  604.   if (!control && CheckSolved(w)) {
  605.     dinoCallbackStruct cb;
  606.  
  607.     cb.reason = DINO_SOLVED;
  608.     XtCallCallbacks((Widget) w, XtNselectCallback, &cb);
  609.   }
  610. }
  611.  
  612. void MoveDino(w, face, position, direction, style, control)
  613.   DinoWidget w;
  614.   int face, position, direction, style, control;
  615. {
  616.   if (control)
  617.     MoveControlCb(w, face, position, direction, style);
  618.   else {
  619.     dinoCallbackStruct cb;
  620.  
  621.     MovePolyhedrons(w, face, position, direction, style);
  622.     cb.reason = DINO_MOVED;
  623.     cb.face = face;
  624.     cb.position = position;
  625.     cb.direction = direction;
  626.     cb.style = style;
  627.     XtCallCallbacks((Widget) w, XtNselectCallback, &cb);
  628.   }
  629.   PutMove(face, position, direction, style, control);
  630. }
  631.  
  632. static void GetColor(w, face, init)
  633.   DinoWidget w;
  634.   int face, init;
  635. {
  636.   XGCValues values;
  637.   XtGCMask valueMask;
  638.   XColor colorCell, rgb;
  639.  
  640.   valueMask = GCForeground | GCBackground;
  641.   values.background = w->core.background_pixel;
  642.   if (w->dino.depth > 1 && !w->dino.mono) {
  643.     if (XAllocNamedColor(XtDisplay(w),
  644.         DefaultColormap(XtDisplay(w), XtWindow(w)),
  645.         w->dino.faceName[face], &colorCell, &rgb)) {
  646.       values.foreground = w->dino.faceColor[face] = colorCell.pixel;
  647.       if (!init)
  648.         XtReleaseGC((Widget) w, w->dino.faceGC[face]);
  649.       w->dino.faceGC[face] = XtGetGC((Widget) w, valueMask, &values);
  650.       return;
  651.     } else {
  652.       char buf[121];
  653.  
  654.       (void) sprintf(buf, "Color name \"%s\" is not defined",
  655.                w->dino.faceName[face]);
  656.       XtWarning(buf);
  657.     }
  658.   }
  659.   values.foreground = w->dino.foreground;
  660.   if (!init)
  661.     XtReleaseGC((Widget) w, w->dino.faceGC[face]);
  662.   w->dino.faceGC[face] = XtGetGC((Widget) w, valueMask, &values);
  663. }
  664.  
  665. static void MoveControlCb(w, face, position, direction, style)
  666.   DinoWidget w;
  667.   int face, position, direction, style;
  668. {
  669.   dinoCallbackStruct cb;
  670.   int newFace, newSide, newDirection, corner, newCorner;
  671.  
  672.   MovePolyhedrons(w, face, position, direction, style);
  673.   cb.reason = DINO_CONTROL;
  674.   cb.face = face;
  675.   cb.position = position;
  676.   cb.direction = direction;
  677.   cb.style = style;
  678.   XtCallCallbacks((Widget) w, XtNselectCallback, &cb);
  679.   if (style == CORNER) {
  680.     newSide = (position + 2) % MAXORIENT;
  681.     MovePolyhedrons(w, face, newSide, direction, MIDDLE);
  682.     cb.face = face;
  683.     cb.position = newSide;
  684.     cb.direction = direction;
  685.     cb.style = MIDDLE;
  686.     XtCallCallbacks((Widget) w, XtNselectCallback, &cb);
  687.     corner = (position - !((position + direction) % 2) + MAXORIENT) % MAXORIENT;
  688.     newFace = oppCorner[face][corner].face;
  689.     newCorner = oppCorner[face][corner].rotation;
  690.     newDirection = 2 * ((direction / 2 + (face != 1 && face != 3)) % 2) +
  691.       !(newCorner % 2);
  692.     newSide = newCorner;
  693.     MovePolyhedrons(w, newFace, newSide, newDirection, CORNER);
  694.     cb.face = newFace;
  695.     cb.position = newSide;
  696.     cb.direction = newDirection;
  697.     cb.style = CORNER;
  698.     XtCallCallbacks((Widget) w, XtNselectCallback, &cb);
  699.   } else if (style == MIDDLE) {
  700.     newSide = (position + 2) % MAXORIENT; 
  701.     MovePolyhedrons(w, face, newSide, direction, CORNER);
  702.     cb.face = face;
  703.     cb.position = newSide;
  704.     cb.direction = direction;
  705.     cb.style = CORNER;
  706.     XtCallCallbacks((Widget) w, XtNselectCallback, &cb);
  707.     corner = (position - !((position + direction) % 2) + MAXORIENT) % MAXORIENT;
  708.     newCorner = oppCorner[face][corner].rotation;
  709.     newFace = oppCorner[face][corner].face;
  710.     if (newFace != 1 && newFace != 3)
  711.       newDirection = (direction + 2) % MAXORIENT;
  712.     else
  713.       newDirection = direction;
  714.     newDirection = 2 * (newDirection / 2) + !(newDirection % 2);
  715.     newSide = (newCorner + 2) % MAXORIENT;
  716.     MovePolyhedrons(w, newFace, newSide, newDirection, CORNER);
  717.     cb.face = newFace;
  718.     cb.position = newSide;
  719.     cb.direction = newDirection;
  720.     cb.style = CORNER;
  721.     XtCallCallbacks((Widget) w, XtNselectCallback, &cb);
  722.   } else if (style == EDGE) {
  723.     newSide = (position + 2) % MAXORIENT; 
  724.     MovePolyhedrons(w, face, newSide, direction, EDGE);
  725.     cb.face = face;
  726.     cb.position = newSide;
  727.     cb.direction = direction;
  728.     cb.style = EDGE;
  729.     XtCallCallbacks((Widget) w, XtNselectCallback, &cb);
  730.   }
  731. }
  732.  
  733. static void CheckPolyhedrons(w)
  734.   DinoWidget w;
  735. {
  736.   if (w->dino.mode < PERIOD2 || w->dino.mode > BOTH) {
  737.     XtWarning("Mode is in error, use 2 for Period2, 3 for Period3, 4 for Both");
  738.     w->dino.mode = DEFAULTMODE;
  739.   }
  740. }
  741.  
  742. static void ResetPolyhedrons(w)
  743.   DinoWidget w;
  744. {
  745.   int face, position;
  746.  
  747.   for (face = 0; face < MAXFACES; face++)
  748.     for (position = 0; position < MAXORIENT; position++) {
  749.       w->dino.cubeLoc[face][position].face = face;
  750.       w->dino.cubeLoc[face][position].rotation = STRT - MAXORIENT;
  751.     }
  752.   FlushMoves(w);
  753.   w->dino.started = FALSE;
  754. }
  755.  
  756. static int SelectPolyhedrons(w, x, y, face, position)
  757.   DinoWidget w;
  758.   int x, y;
  759.   int *face;
  760.   int *position;
  761. {
  762.   if (w->dino.dim == 2)
  763.     return SelectPolyhedrons2D((Dino2DWidget) w, x, y,
  764.       face, position);
  765.   else if (w->dino.dim == 3)
  766.     return SelectPolyhedrons3D((Dino3DWidget) w, x, y,
  767.       face, position);
  768.   return FALSE;
  769. }
  770.  
  771. static int NarrowSelection(w, face, direction)
  772.   DinoWidget w;
  773.   int *face;
  774.   int *direction;
  775. {
  776.   if (w->dino.dim == 2)
  777.     return NarrowSelection2D((Dino2DWidget) w, face, direction);
  778.   else if (w->dino.dim == 3)
  779.     return NarrowSelection3D((Dino3DWidget) w, face, direction);
  780.   return FALSE;
  781. }
  782.  
  783. static int PositionPolyhedrons(w, x, y, face, position, direction)
  784.   DinoWidget w;
  785.   int x, y;
  786.   int *face;
  787.   int *position;
  788.   int *direction;
  789. {
  790.   if (!SelectPolyhedrons(w, x, y, face, position))
  791.     return FALSE;
  792.   return NarrowSelection(w, face, direction);
  793. }
  794.  
  795. static int GetStyle(w, shift, control, alt)
  796.   DinoWidget w;
  797.   int shift, control, alt;
  798. {
  799.   if (w->dino.mode != BOTH) {
  800.     if (control && shift) {
  801.       if (w->dino.mode == PERIOD3)
  802.         return EDGE;
  803.       else if (alt)
  804.         return MIDDLE;
  805.       else
  806.         return CORNER;
  807.     } else if (w->dino.mode == PERIOD2)
  808.       return EDGE;
  809.     else if (alt)
  810.       return MIDDLE;
  811.     else
  812.       return CORNER;
  813.   } else {
  814.     if (shift)
  815.       return EDGE;
  816.     else {
  817.       if (alt)
  818.         return MIDDLE;
  819.       else
  820.         return CORNER;
  821.     }
  822.   }
  823. }
  824. static void MoveNoPolyhedrons(w)
  825.   DinoWidget w;
  826. {
  827.   dinoCallbackStruct cb;
  828.  
  829.   cb.reason = DINO_ILLEGAL;
  830.   XtCallCallbacks((Widget) w, XtNselectCallback, &cb);
  831. }
  832.  
  833. static void PracticePolyhedrons(w)
  834.   DinoWidget w;
  835. {
  836.   dinoCallbackStruct cb;
  837.  
  838.   cb.reason = DINO_PRACTICE;
  839.   XtCallCallbacks((Widget) w, XtNselectCallback, &cb);
  840. }
  841.  
  842. static void RandomizePolyhedrons(w)
  843.   DinoWidget w;
  844. {
  845.   dinoCallbackStruct cb;
  846.   int face, position, direction, style;
  847.   int big = MAXORIENT * 3 + NRAND(2);
  848.  
  849.   if (w->dino.practice)
  850.     PracticePolyhedrons(w);
  851.   cb.reason = DINO_RESET;
  852.   XtCallCallbacks((Widget) w, XtNselectCallback, &cb);
  853.  
  854. #ifdef DEBUG
  855.   big = 3;
  856. #endif
  857.  
  858.   while (big--) {
  859.     face = NRAND(MAXFACES);
  860.     position = NRAND(MAXORIENT);
  861.     direction = ((NRAND(2)) ? position + 1 : position + 3) % MAXORIENT;
  862.     if (w->dino.mode == PERIOD2)
  863.       style = EDGE;
  864.     else if (w->dino.mode == BOTH)
  865.       style = NRAND(3);
  866.     else
  867.       style = NRAND(2);
  868.     MoveDino(w, face, position, direction, style, FALSE);
  869.   }
  870.   FlushMoves(w);
  871.   cb.reason = DINO_RANDOMIZE;
  872.   XtCallCallbacks((Widget) w, XtNselectCallback, &cb);
  873.   if (CheckSolved(w)) {
  874.     cb.reason = DINO_SOLVED;
  875.     XtCallCallbacks((Widget) w, XtNselectCallback, &cb);
  876.   }
  877. }
  878.  
  879. static void MovePolyhedrons(w, face, position, direction, style)
  880.   DinoWidget w;
  881.   int face, position, direction, style;
  882. {
  883.   int corner, newCorner;
  884.  
  885.   corner = (position - !((position + direction) % 2) + MAXORIENT) % MAXORIENT;
  886.   if (style == CORNER) {
  887.     MoveInsideCorners(w, face, corner, direction);
  888.   } else if (style == MIDDLE) {
  889.     MoveOutsideCorners(w, face, corner, direction);
  890.     newCorner = oppCorner[face][corner].rotation;
  891.     face = oppCorner[face][corner].face;
  892.     if (((face != 1 && face != 3) + corner) % 2)
  893.       direction = (direction + 1) % MAXORIENT;
  894.     else
  895.       direction = (direction + 3) % MAXORIENT;
  896.     corner = newCorner;
  897.     MoveOutsideCorners(w, face, corner, direction);
  898.   } else if (style == EDGE) {
  899.     MoveEdges(w, face, corner, direction);
  900.     MoveFaces(w, face, corner,
  901.       ((face == 2 || face == 5) ? CCW : HALF) % MAXORIENT);
  902.   } else {
  903.     int k, newFace, rotate, newDirection;
  904.  
  905.     RotateFace(w, faceToRotate[face][direction % MAXORIENT], CW);
  906.     RotateFace(w, faceToRotate[face][(direction + 2) % MAXORIENT], CCW);
  907.     ReadFace((DinoWidget) w, face, 0);
  908.     for (k = 1; k <= MAXORIENT; k++) {
  909.       newFace = slideNextFace[face][direction % MAXORIENT].face;
  910.       rotate = slideNextFace[face][direction % MAXORIENT].rotation;
  911.       newDirection = (rotate + direction) % MAXORIENT;
  912.       if (k != MAXORIENT)
  913.         ReadFace((DinoWidget) w, newFace, k);
  914.       WriteFace(w, newFace, rotate, k - 1);
  915.       face = newFace;
  916.       direction = newDirection;
  917.     }
  918.   }
  919. }
  920.  
  921. static void MoveInsideCorners(w, face, corner, direction)
  922.   DinoWidget w;
  923.   int face, corner, direction;
  924. {
  925.   int newFace, newCorner, newDirection, dir, k;
  926.  
  927.   ReadDiagonal((DinoWidget) w, face, corner, 0);
  928.   for (k = 1; k <= MAXROTATE; k++) {
  929.     dir = direction / 2;
  930.     newFace = slideCorner[face][corner][dir].face;
  931.     newCorner = slideCorner[face][corner][dir].side;
  932.     newDirection = 2 * slideCorner[face][corner][dir].dir + !(newCorner % 2);
  933.     if (k != MAXROTATE)
  934.       ReadDiagonal((DinoWidget) w, newFace, newCorner, k);
  935.     WriteDiagonal(w, newFace, newCorner,
  936.       (newDirection - direction + MAXORIENT) % MAXORIENT, k - 1);
  937.     face = newFace;
  938.     corner = newCorner;
  939.     direction = newDirection;
  940.   }
  941. }
  942.  
  943. static void MoveOutsideCorners(w, face, corner, direction)
  944.   DinoWidget w;
  945.   int face, corner, direction;
  946. {
  947.   int newFace, newCorner, newDirection, dir, k;
  948.  
  949.   ReadDiagonal((DinoWidget) w, face, corner, 0);
  950.   for (k = 1; k <= MAXROTATE; k++) {
  951.     corner = (corner + 2) % MAXORIENT;
  952.     dir = direction / 2;
  953.     newFace = slideCorner[face][corner][dir].face;
  954.     newCorner = (slideCorner[face][corner][dir].side + 2) % MAXORIENT;
  955.     newDirection = 2 * slideCorner[face][corner][dir].dir + !(newCorner % 2);
  956.     if (k != MAXROTATE)
  957.       ReadDiagonal((DinoWidget) w, newFace, newCorner, k);
  958.     WriteDiagonal(w, newFace, newCorner,
  959.       (newDirection - direction + MAXORIENT) % MAXORIENT, k - 1);
  960.     face = newFace;
  961.     corner = newCorner;
  962.     direction = newDirection;
  963.   }
  964. }
  965.  
  966. static void MoveEdges(w, face, corner, direction)
  967.   DinoWidget w;
  968.   int face, corner, direction;
  969. {
  970.   int k, newFace, rotate, newCorner, newDirection;
  971.  
  972.   ReadDiagonal((DinoWidget) w, face, corner, 0);
  973.   for (k = 1; k <= 2; k++) {
  974.     newFace = oppFace[face];
  975.     /*rotate = (((face == 1 || face == 3) ? 1 : 3) + 3 * direction) %
  976.       MAXORIENT;*/
  977.     newCorner = ((((face == 1 || face == 3) + corner) % 2) ?
  978.       (corner + 3) : (corner + 1)) % MAXORIENT;
  979.    rotate = (newCorner - corner + MAXORIENT) % MAXORIENT; 
  980.    newDirection = (rotate + direction) % MAXORIENT;
  981.     if (k != 2)
  982.       ReadDiagonal((DinoWidget) w, newFace, newCorner, k);
  983.     WriteDiagonal(w, newFace, newCorner, rotate, k - 1);
  984.     face = newFace;
  985.     corner = newCorner;
  986.     direction = newDirection;
  987.   }
  988. }
  989.  
  990. static void MoveFaces(w, f, d, rotate)
  991.   DinoWidget w;
  992.   int f, d, rotate;
  993. {
  994.   int k, face, newFace;
  995.  
  996.   face = faceToRotate2[f][d][0],
  997.   ReadFace((DinoWidget) w, face, 0);
  998.   for (k = 1; k <= 2; k++) {
  999.     newFace = faceToRotate2[f][d][k % 2],
  1000.     rotate = MAXORIENT - rotate;
  1001.     if (k != 2)
  1002.       ReadFace((DinoWidget) w, newFace, k);
  1003.     WriteFace(w, newFace, rotate, k - 1);
  1004.     face = newFace;
  1005.   }
  1006. }
  1007.  
  1008. static void ReadDiagonal(w, face, corner, h)
  1009.   DinoWidget w;
  1010.   int face, corner, h; 
  1011. {
  1012.   w->dino.spindleLoc[h][0] = w->dino.cubeLoc[face][corner];
  1013.   w->dino.spindleLoc[h][1] = w->dino.cubeLoc[face][(corner + 1) % MAXORIENT];
  1014. }
  1015.  
  1016. static void WriteDiagonal(w, face, corner, rotate, h)
  1017.   DinoWidget w;
  1018.   int face, corner, rotate, h;
  1019. {
  1020.   w->dino.spindleLoc[h][0].rotation =
  1021.     (w->dino.spindleLoc[h][0].rotation + rotate) % MAXORIENT;
  1022.   w->dino.spindleLoc[h][1].rotation =
  1023.     (w->dino.spindleLoc[h][1].rotation + rotate) % MAXORIENT;
  1024.   w->dino.cubeLoc[face][corner] = w->dino.spindleLoc[h][0];
  1025.   DrawTriangle(w, face, corner, FALSE); 
  1026.   w->dino.cubeLoc[face][(corner + 1) % MAXORIENT] = w->dino.spindleLoc[h][1];
  1027.   DrawTriangle(w, face, (corner + 1) % MAXORIENT, FALSE); 
  1028. }
  1029.  
  1030. static void ReadFace(w, face, h)
  1031.   DinoWidget w;
  1032.   int face, h;
  1033. {
  1034.   int side;
  1035.  
  1036.   for (side = 0; side < MAXORIENT; side++)
  1037.     w->dino.rowLoc[h][side] = w->dino.cubeLoc[face][side];
  1038. }
  1039.  
  1040. static void WriteFace(w, face, rotate, h)
  1041.   DinoWidget w;
  1042.   int face, rotate, h;
  1043. {
  1044.   int side, newSide;
  1045.  
  1046.   for (side = 0; side < MAXORIENT; side++) {
  1047.     newSide = (side + rotate) % MAXORIENT;
  1048.     w->dino.cubeLoc[face][newSide] = w->dino.rowLoc[h][side];
  1049.     w->dino.cubeLoc[face][newSide].rotation =
  1050.       (w->dino.cubeLoc[face][newSide].rotation + rotate) % MAXORIENT;
  1051.     DrawTriangle(w, face, (side + rotate) % MAXORIENT, FALSE);
  1052.   }
  1053. }
  1054.  
  1055. static void RotateFace(w, face, direction)
  1056.   DinoWidget w;
  1057.   int face, direction;
  1058. {
  1059.   int side;
  1060.  
  1061.   /* Read Face */
  1062.   for (side = 0; side < MAXORIENT; side++)
  1063.     w->dino.faceLoc[side] = w->dino.cubeLoc[face][side];
  1064.   /* Write Face */
  1065.   for (side = 0; side < MAXORIENT; side++) {
  1066.     w->dino.cubeLoc[face][side] = (direction == CW) ?
  1067.       w->dino.faceLoc[(side + MAXORIENT - 1) % MAXORIENT]:
  1068.       w->dino.faceLoc[(side + 1) % MAXORIENT];
  1069.     w->dino.cubeLoc[face][side].rotation =
  1070.       (w->dino.cubeLoc[face][side].rotation + direction) % MAXORIENT;
  1071.     DrawTriangle(w, face, side, FALSE);
  1072.   }
  1073. }
  1074.  
  1075. void DrawAllPolyhedrons(w)
  1076.   DinoWidget w;
  1077. {
  1078.   int face, position;
  1079.  
  1080.   for (face = 0; face < MAXFACES; face++)
  1081.     for (position = 0; position < MAXORIENT; position++)
  1082.       DrawTriangle(w, face, position, FALSE);
  1083. }
  1084.  
  1085. static void DrawTriangle(w, face, position, offset)
  1086.   DinoWidget w;
  1087.   int face, position, offset;
  1088. {
  1089.   if (w->dino.dim == 2)
  1090.     DrawTriangle2D((Dino2DWidget) w, face, position, offset);
  1091.   else if (w->dino.dim == 3)
  1092.     DrawTriangle3D((Dino3DWidget) w, face, position, offset);
  1093. }
  1094.  
  1095. Boolean CheckSolved(w)
  1096.   DinoWidget w;
  1097. {
  1098.   int face, position;
  1099.   DinoCornerLoc test;
  1100.  
  1101.   for (face = 0; face < MAXFACES; face++)
  1102.     for (position = 0; position < MAXORIENT; position++) {
  1103.       if (!position) {
  1104.         test.face = w->dino.cubeLoc[face][position].face;
  1105.         test.rotation = w->dino.cubeLoc[face][position].rotation;
  1106.       } else if (test.face != /*face*/
  1107.                w->dino.cubeLoc[face][position].face ||
  1108.                (w->dino.orient && test.rotation != /*STRT - MAXORIENT*/
  1109.                 w->dino.cubeLoc[face][position].rotation))
  1110.         return FALSE;
  1111.     }
  1112.   return TRUE;
  1113. }
  1114.  
  1115. static int CheckMoveDir(position1, position2, direction)
  1116.   int position1, position2, *direction;
  1117. {
  1118.   if (!((position1 - position2 + MAXORIENT) % 2))
  1119.     return FALSE;
  1120.   switch (position1) {
  1121.     case 0:
  1122.       *direction = (position2 == 1) ? 1 : 2;
  1123.       break;
  1124.     case 1:
  1125.       *direction = (position2 == 2) ? 2 : 3;
  1126.       break;
  1127.     case 2:
  1128.       *direction = (position2 == 3) ? 3 : 0;
  1129.       break;
  1130.     case 3:
  1131.       *direction = (position2 == 0) ? 0 : 1;
  1132.       break;
  1133.     default:
  1134.       return FALSE;
  1135.   }
  1136.   return TRUE;
  1137. }
  1138.  
  1139. #ifdef DEBUG
  1140.  
  1141. void PrintCube(w)
  1142.   DinoWidget w;
  1143. {
  1144.   int face, position;
  1145.  
  1146.   for (face = 0; face < MAXFACES; face++) {
  1147.     for (position = 0; position < MAXORIENT; position++)
  1148.       (void) printf("%d %d  ", w->dino.cubeLoc[face][position].face,
  1149.                w->dino.cubeLoc[face][position].rotation);
  1150.     (void) printf("\n");
  1151.   }
  1152.   (void) printf("\n");
  1153. }
  1154.  
  1155. #endif
  1156.